package cn.jsu.oj.dispatchServer.thread;

import cn.jsu.oj.dispatchServer.dataStructure.MappingQueue;
import cn.jsu.oj.dispatchServer.init.JudgeClient;
import cn.jsu.oj.dispatchServer.pojo.TaskInfo;
import cn.jsu.oj.dispatchServer.pojo.TaskSumInfo;
import cn.jsu.oj.dispatchServer.resource.Resource;
import lombok.extern.slf4j.Slf4j;

import java.time.Instant;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author ahtonc
 */
@Slf4j
public class DispatchThread implements Runnable {


    public static CopyOnWriteArrayList<JudgeClient> judgeMap;

    /**
     *
     * @param judgeClient
     */
    public static void addJudgeClient(JudgeClient judgeClient) {
        synchronized (judgeMap) {
            judgeMap.add(judgeClient);
            if (judgeMap.size() == 1) {
                judgeMap.notify();
            }
        }
    }

    static {
        judgeMap = new CopyOnWriteArrayList<>();
    }

    @Override
    public void run() {
        while (true) {
            try {
                //获取任务
                TaskInfo take = Resource.taskBigQueue.take();
                if (judgeMap.size() == 0) {
                    synchronized (judgeMap) {
                        log.warn("任务调度暂未连接判题机，等待中....");
                        judgeMap.wait();
                    }
                }
                //选择一个判题机
                JudgeClient select = select(take,take.getSerialNumber(),1);
//                //改变weight
//                select.getMappingQueue().changeWeight(take.getTaskWeight());
                //添加任务
                select.getMappingQueue().add(take);
                //设置暂存任务时间戳
//                take.setTimeStamp(System.currentTimeMillis());
                //添加暂存
                select.getStoreMap().put(take.getSerialNumber(), take);
                log.info("缓存队列大小: {}",select.getStoreMap().size() );
                select.getChannel().writeAndFlush(new TaskSumInfo(select.getMappingQueue().size()).serialize());
                log.info("映射队列大小" + select.getMappingQueue().size());
            } catch (Exception e) {
                log.error(e.getLocalizedMessage(),e);
            }
        }
    }

    /**
     *目前是轮询判题机 ，为了做队列的校验，采用递归
     */
    public static JudgeClient select(TaskInfo taskInfo,long serialNumber,int traceCount) throws Exception {
        if (traceCount > judgeMap.size()) {
           Resource.taskBigQueue.add(taskInfo);
           throw new Exception("所有映射队列长度已满，任务重回大队列");
        }
        long judgeClientIndex = serialNumber % (long)judgeMap.size();
        JudgeClient selector = judgeMap.get((int) judgeClientIndex);
        log.info("判题机数:" + judgeMap.size() + ",选择" + judgeClientIndex);
        if (  selector.getMappingQueue().size() < 100) {
            return selector;
        }
        else {
            traceCount += 1;
            return select(taskInfo,serialNumber +1,traceCount);
        }

        //        int min = Integer.MAX_VALUE;
//        JudgeClient selector = null;
//        while (selector == null) {
//            for (JudgeClient client : judgeMap) {
//                if (client.getMappingQueue().size() < 100 && client.getMappingQueue().getWeight() <= min) {
//                    min = client.getMappingQueue().getWeight();
//                    selector = client;
//                }
//            }
//        }

    }

    private void send(MappingQueue<TaskInfo> mappingQueue) {

    }
}

